<?php

/**
 * Базовый класс фильтров - компонентов, участвующих в обработке пользовательского
 * запроса.
 *
 */
abstract class Kernel_Filter extends Kernel_Component implements Kernel_Filter_Interface {

    /**
     * Запускает фильтр.
     *
     */
    public function process() 
    {
        if (!$this->_allowed()) {
            $this->_deny('Not allowed');
        }
    }

    /**
     * Возвращает, разрешено ли использование фильтра в текущем контексте.
     * Например, текущим пользователем.
     *
     * @return  boolean
     */
    protected function _allowed() {
        return true;
    }

    /**
     * Передает управление указанному фильтру.
     *
     * @param   Kernel_Filter_Interface $filter
     * @return  Kernel_Filter
     */
    protected function _forward(Kernel_Filter_Interface $filter) {
        $filter->process();
        return $this;
    }

    /**
     * Прерывает обработку запроса и генерирует ошибку "NotFound".
     *
     * @param   string  $message
     * @throws  Kernel_Filter_Exception_NotFound
     */
    protected function _abort($message) {
        throw new Kernel_Filter_Exception_NotFound($this->_specialize($message));
    }

    /**
     * Прерывает обработку запроса и генерирует ошибку "Forbidden".
     *
     * @param   string  $message
     * @param   boolean $force
     * @throws  Kernel_Filter_Exception
     */
    protected function _deny($message, $force = false) {
        if (!$force && !User_Session::isAuthorized()
            // :KLUDGE: morozov 13022008: уродско, но работает как надо.
            && Kernel_Mode_Factory::get() instanceof Kernel_Mode_Html) {
            $this->_location('user/login/?back=' . urlencode(Application::getRequest()->requestUri()));
        } else {
            throw new Kernel_Filter_Exception_Forbidden($this->_specialize($message));
        }
    }

    /**
     * Прерывает обработку запроса и перенаправляет агента по указанному URL.
     *
     * @param   string  $url
     * @param   boolean $permanent
     */
    protected function _location($url, $permanent = false) {
        throw $permanent
            ? new Kernel_Filter_Exception_Location_MovedPermanently($url)
            : new Kernel_Filter_Exception_Location_Found($url);
    }

    /**
     * Прерывает обработку запроса и перезагружает страницу.
     *
     */
    protected function _reload() {
        $this->_location('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
    }

    /**
     * Дописывает к сообщению префикс для уточнения, какой именно из фильтров
     * бросает исключение.
     *
     * @param   string  $message
     * @return  string
     */
    private function _specialize($message) {
        return get_class($this) . ': ' . $message;
    }
}
